package parachute;
import hla.rti.AttributeHandleSet;
import hla.rti.FederationExecutionAlreadyExists;
import hla.rti.LogicalTime;
import hla.rti.LogicalTimeInterval;
import hla.rti.RTIambassador;
import hla.rti.RTIexception;
import hla.rti.ResignAction;
import hla.rti.SuppliedAttributes;
import hla.rti.jlc.EncodingHelpers;
import hla.rti.jlc.RtiFactoryFactory;
import java.io.File;
import java.net.MalformedURLException;
import org.portico.impl.hla13.types.DoubleTime;
import org.portico.impl.hla13.types.DoubleTimeInterval;
import core.Logger;
import core.Parachute;
import core.Plane;
import core.Parachute.ParachuteStatus;
public class ParachuteManager {
private RTIambassador rtiAmbassador = null;
private ParachuteFederateAmbassador foAmbassador = null;
private Plane plane = new Plane();
private Parachute flyingObject = new Parachute();
private Logger logger = new FlyingObjectLogger();
private boolean planeFlies = true;
double timestep = 1.0;
int flightGearHandle;
int fgAltitudeHandle;
int fgLatitudeHandle;
int fgLongitudeHandle;
int fgVelocityHandle;
/** The sync point all federates will sync up on before starting */
public static final String READY_TO_RUN = "ReadyToRun";
int parachuteStatusInteraction;
int readyStatus;
public ParachuteManager() {
try {
rtiAmbassador = RtiFactoryFactory.getRtiFactory()
.createRtiAmbassador();
try {
File fom = new File("TrajectorySim.xml");
rtiAmbassador.createFederationExecution("FlightGearSimulation",
fom.toURI().toURL());
logger.log("Created Federation");
} catch (FederationExecutionAlreadyExists exists) {
logger.log("Didn't create federation, it already existed");
} catch (MalformedURLException urle) {
urle.printStackTrace();
return;
}
} catch (RTIexception e) {
e.printStackTrace();
}
}
public void runFederate(String federateName) throws RTIexception {
foAmbassador = new ParachuteFederateAmbassador(this, plane);
rtiAmbassador.joinFederationExecution(federateName,
"FlightGearSimulation", foAmbassador);
logger.log("Joined Federation as " + federateName);
// 4. announce the sync point //
// //////////////////////////////
// announce a sync point to get everyone on the same page. if the point
// has already been registered, we'll get a callback saying it failed,
// but we don't care about that, as long as someone registered it
rtiAmbassador
.registerFederationSynchronizationPoint(READY_TO_RUN, null);
// wait until the point is announced
while (foAmbassador.isAnnounced() == false) {
rtiAmbassador.tick();
}
enableTimePolicy();
logger.log("Time Policy Enabled");
publishAndSubscribe();
int objectHandle = registerObject();
logger.log("Registered Object, handle=" + objectHandle);
while (planeFlies && !flyingObject.isLanded()) {
// update coordinates of the missile
updateAttributeValues(objectHandle);
// request a time advance and wait until we get it
advanceTime();
}
// We now shot the object :D lets send last status
// of the parachute object (which is SHOT) and unregister our federate
updateAttributeValues(objectHandle);
advanceTime();
// ////////////////////////////////////
// 10. delete the object we created //
// ////////////////////////////////////
deleteObject(objectHandle);
// logger.log( "Deleted Object, handle=" + objectHandle );
// //////////////////////////////////
// 11. resign from the federation //
// //////////////////////////////////
rtiAmbassador.resignFederationExecution(ResignAction.NO_ACTION);
logger.log("Resigned from Federation");
}
/**
* This method will attempt to enable the various time related properties
* for the federate
*/
private void enableTimePolicy() throws RTIexception {
LogicalTime currentTime = convertTime(foAmbassador.getFederateTime());
LogicalTimeInterval lookahead = convertInterval(foAmbassador
.getFederateLookahead());
// //////////////////////////
// enable time regulation //
// //////////////////////////
rtiAmbassador.enableTimeRegulation(currentTime, lookahead);
// tick until we get the callback
while (!foAmbassador.isRegulating()) {
rtiAmbassador.tick();
}
// ///////////////////////////
// enable time constrained //
// ///////////////////////////
rtiAmbassador.enableTimeConstrained();
// tick until we get the callback
while (!foAmbassador.isConstrained()) {
rtiAmbassador.tick();
}
}
/**
*/
private void publishAndSubscribe() throws RTIexception {
flightGearHandle = rtiAmbassador
.getObjectClassHandle("HLAobjectRoot.FlightGear");
fgAltitudeHandle = rtiAmbassador.getAttributeHandle("Altitude",
flightGearHandle);
fgLatitudeHandle = rtiAmbassador.getAttributeHandle("Latitude",
flightGearHandle);
fgLongitudeHandle = rtiAmbassador.getAttributeHandle("Longitude",
flightGearHandle);
fgVelocityHandle = rtiAmbassador.getAttributeHandle("Velocity",
flightGearHandle);
AttributeHandleSet attributes = RtiFactoryFactory.getRtiFactory()
.createAttributeHandleSet();
attributes.add(fgAltitudeHandle);
attributes.add(fgLatitudeHandle);
attributes.add(fgLongitudeHandle);
attributes.add(fgVelocityHandle);
rtiAmbassador.subscribeObjectClassAttributes(flightGearHandle,
attributes);
int parachuteHandle = rtiAmbassador
.getObjectClassHandle("HLAobjectRoot.Parachute");
attributes = RtiFactoryFactory.getRtiFactory()
.createAttributeHandleSet();
attributes.add(rtiAmbassador.getAttributeHandle("Altitude",
parachuteHandle));
attributes.add(rtiAmbassador.getAttributeHandle("Latitude",
parachuteHandle));
attributes.add(rtiAmbassador.getAttributeHandle("Longitude",
parachuteHandle));
attributes.add(rtiAmbassador.getAttributeHandle("Status",
parachuteHandle));
rtiAmbassador.publishObjectClass(parachuteHandle, attributes);
int parachuteCommandHandle = rtiAmbassador
.getInteractionClassHandle("HLAinteractionRoot.ParachuteCommand");
rtiAmbassador.subscribeInteractionClass(parachuteCommandHandle);
}
/**
*/
private int registerObject() throws RTIexception {
int classHandle = rtiAmbassador
.getObjectClassHandle("HLAobjectRoot.Parachute");
return rtiAmbassador.registerObjectInstance(classHandle);
}
/**
*/
private void updateAttributeValues(int objectHandle) throws RTIexception {
SuppliedAttributes attributes = RtiFactoryFactory.getRtiFactory()
.createSuppliedAttributes();
// get the handles
// this line gets the object class of the instance identified by the
// object instance the handle points to
int classHandle = rtiAmbassador.getObjectClass(objectHandle);
int altitudeHandle = rtiAmbassador.getAttributeHandle("Altitude",
classHandle);
int latitudeHandle = rtiAmbassador.getAttributeHandle("Latitude",
classHandle);
int longitudeHandle = rtiAmbassador.getAttributeHandle("Longitude",
classHandle);
int statusHandle = rtiAmbassador.getAttributeHandle("Status",
classHandle);
double altitude = flyingObject.getAltitude();
double longitude = flyingObject.getLongitude();
double latitude = flyingObject.getLatitude();
if (flyingObject.isWaitingFireSignal()) {
altitude = plane.getAltitude();
longitude = plane.getLontitude();
latitude = plane.getLatitude();
}
logger.log("sending update... " + altitude);
byte[] altitudeValue = EncodingHelpers.encodeString(String
.valueOf(altitude));
attributes.add(altitudeHandle, altitudeValue);
byte[] latitudeValue = EncodingHelpers.encodeString(String
.valueOf(latitude));
attributes.add(latitudeHandle, latitudeValue);
byte[] longitudeValue = EncodingHelpers.encodeString(String
.valueOf(longitude));
attributes.add(longitudeHandle, longitudeValue);
byte[] statusValule = EncodingHelpers.encodeString(flyingObject
.getStatus().toString());
attributes.add(statusHandle, statusValule);
LogicalTime time = convertTime(foAmbassador.getFederateTime()
+ foAmbassador.getFederateLookahead());
rtiAmbassador.updateAttributeValues(objectHandle, attributes,
"Parachute: ".getBytes(), time);
}
/**
*/
private void deleteObject(int handle) throws RTIexception {
rtiAmbassador.deleteObjectInstance(handle, null); // no tag, we're lazy
}
/**
* This method will request a time advance to the current time, plus the
* given timestep. It will then wait until a notification of the time
* advance grant has been received.
*/
private void advanceTime() throws RTIexception {
// request the advance
foAmbassador.setAdvancing(true);
LogicalTime newTime = convertTime(foAmbassador.getFederateTime()
+ timestep);
rtiAmbassador.timeAdvanceRequest(newTime);
// wait for the time advance to be granted. ticking will tell the
// LRC to start delivering callbacks to the federate
while (foAmbassador.isAdvancing()) {
rtiAmbassador.tick();
}
}
/**
* Jump message is fired. This message will be taken from FlightGear
*/
public void jump() {
logger.log("fire missile called: ");
Runnable r = new Runnable() {
@Override
public void run() {
double planeAltitude = plane.getAltitude();
flyingObject.setAltitude(planeAltitude);
flyingObject.setLatitude(plane.getLatitude());
flyingObject.setLongitude(plane.getLontitude());
flyingObject.fire();
while (!flyingObject.isAltitudeZero()) {
try {
Thread.sleep(1000);
flyingObject.move();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
flyingObject.setStatus(ParachuteStatus.LANDED);
}
};
new Thread(r).start();
}
/**
* As all time-related code is Portico-specific, we have isolated it into a
* single method. This way, if you need to move to a different RTI, you only
* need to change this code, rather than more code throughout the whole
* class.
*/
private LogicalTime convertTime(double time) {
// PORTICO SPECIFIC!!
return new DoubleTime(time);
}
/**
* Same as for {@link #convertTime(double)}
*/
private LogicalTimeInterval convertInterval(double time) {
// PORTICO SPECIFIC!!
return new DoubleTimeInterval(time);
}
/**
*
* @param args
*/
public static void main(String[] args) {
final ParachuteManager flyingObjectManager = new ParachuteManager();
try {
flyingObjectManager.runFederate("Puma");
// flyingObjectManager.fireMissile();
} catch (RTIexception e) {
e.printStackTrace();
}
}
public void setPlaneStatus(boolean b) {
planeFlies = b;
}
}